From 2248727b1d267ebd3debfc0d1c807b247dc62cfa Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 27 Mar 2008 11:39:57 +0000 Subject: [PATCH] x86, hvm: MMIO emulations should defer domain shutdown requests until the relevant instruction has been fully emulated (which may require multiple round trips to qemu-dm). Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/io.c | 19 +++++++++---------- xen/common/domain.c | 6 ++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index bc5f8acce3..ac1e62782a 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -221,35 +221,34 @@ int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn) void hvm_io_assist(void) { - struct vcpu *v = current; - ioreq_t *p = &get_ioreq(v)->vp_ioreq; + struct vcpu *curr = current; + ioreq_t *p = &get_ioreq(curr)->vp_ioreq; enum hvm_io_state io_state; if ( p->state != STATE_IORESP_READY ) { gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state); - domain_crash(v->domain); - goto out; + domain_crash_synchronous(); } rmb(); /* see IORESP_READY /then/ read contents of ioreq */ p->state = STATE_IOREQ_NONE; - io_state = v->arch.hvm_vcpu.io_state; - v->arch.hvm_vcpu.io_state = HVMIO_none; + io_state = curr->arch.hvm_vcpu.io_state; + curr->arch.hvm_vcpu.io_state = HVMIO_none; if ( (io_state == HVMIO_awaiting_completion) || (io_state == HVMIO_handle_mmio_awaiting_completion) ) { - v->arch.hvm_vcpu.io_state = HVMIO_completed; - v->arch.hvm_vcpu.io_data = p->data; + curr->arch.hvm_vcpu.io_state = HVMIO_completed; + curr->arch.hvm_vcpu.io_data = p->data; if ( io_state == HVMIO_handle_mmio_awaiting_completion ) (void)handle_mmio(); } - out: - vcpu_end_shutdown_deferral(v); + if ( p->state == STATE_IOREQ_NONE ) + vcpu_end_shutdown_deferral(curr); } void dpci_ioport_read(uint32_t mport, ioreq_t *p) diff --git a/xen/common/domain.c b/xen/common/domain.c index bc9a7d9fad..45a9de6a9c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -393,6 +393,8 @@ void __domain_crash_synchronous(void) this_cpu(mc_state).flags = 0; } + vcpu_end_shutdown_deferral(current); + for ( ; ; ) do_softirq(); } @@ -459,10 +461,14 @@ void domain_resume(struct domain *d) int vcpu_start_shutdown_deferral(struct vcpu *v) { + if ( v->defer_shutdown ) + return 1; + v->defer_shutdown = 1; smp_mb(); /* set deferral status /then/ check for shutdown */ if ( unlikely(v->domain->is_shutting_down) ) vcpu_check_shutdown(v); + return v->defer_shutdown; } -- 2.30.2